﻿using AutoMapper;
using Microsoft.Extensions.Logging;
using Msung.Business.IService;
using Msung.Core;
using Msung.Core.Caching;
using Msung.Core.Extensions;
using Msung.Core.Kafka;
using Msung.Core.Kafka.Integration;
using Msung.Core.Snowflake;
using Msung.Repository.Entity;
using Newtonsoft.Json;
using DataTraceService.IService;
using DataTraceService.Model;
using Msung.Business.IService.MSUNG;
using Msung.Business.Model.COLLECTION;
using Msung.Business.Model.TRACER;
using Msung.Business.Model;

namespace DataTraceService.Consumers
{
    public class BmConsumerListener : IKafkaConsumerListener
    {
        readonly IRedisOperationRepository _redisRepository;
        readonly IFlowcardService _flowService;
        private readonly ILogger<BmConsumerListener> _logger;
        readonly IWaferService _waferService;

        public BmConsumerListener(
            ILogger<BmConsumerListener> logger,
            IRedisOperationRepository redisRepository,
            IFlowcardService flowService,
            IWaferService waferService
            )
        {
            this._redisRepository = redisRepository;
            _logger = logger;
            _flowService = flowService;
            _waferService = waferService;
        }
        public void ConsumeAsync(RecieveResult recieveResult)
        {
            _logger.logInfo($"{typeof(BmConsumerListener).Name} recieve message:{recieveResult.Message} location:{recieveResult.Offset} partition:{recieveResult.Partition} key:{recieveResult.Key} ");
            try
            {
                var model = recieveResult.GetRecieveMessage<BM_MODEL>();
                if (model == null)
                {
                    return;
                }

                if (string.IsNullOrWhiteSpace(model.Struid) && model.WaferID == null)
                {
                    recieveResult.Commit();
                    return;
                }
                if (string.IsNullOrWhiteSpace(model.Struid))
                {
                    model.Struid = $"{model.EID}_{DateTimeOffset.Now.ToUnixTimeSeconds()}";
                }

                switch (model.UpDown)
                {
                    case 0:
                        UPBasketTask(model);
                        break;
                    case 2:
                        DownBasketTask(model);
                        break;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, ex.Message);
            }
            recieveResult.Commit();
        }
        #region 上/下花篮逻辑
        /// <summary>
        /// 上料处理逻辑
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void UPBasketTask(BM_MODEL model)
        {
            if (model == null) return;
            BasketModel basket = new BasketModel()
            {
                Eid = model.EID,
                Pid = model.Pid,
                Buid = model.Struid,
                Struid = model.Struid,
                ChannelNo = int.Parse(model.CHANEL),
                UpDown = model.UpDown,
                BoatNo = model.BoatIDNotify1,
                GrooveNo = model.BoatDataPostion1,
                ProcessTime = model.CreatedTime,
                Status = "0"
            };

            string? flowNo = _redisRepository.Get($"FlowCard:{model.Struid}");
            flowNo = flowNo?.Replace("\"", "");

            FlowCardInput? flowInput = string.IsNullOrWhiteSpace(flowNo) ? null : _redisRepository.Get<FlowCardInput>("FlowNo:" + flowNo);
            string process = (int.Parse(model.Pid) - 1).ToString();
            if (flowInput == null || int.Parse(flowInput.CURRENTPROCESS) >= int.Parse(model.Pid))
            {
                string log = flowInput == null ? "null-" + flowNo : JsonConvert.SerializeObject(flowInput);
                _logger.LogDebug("BM创建流程卡：" + log);
                flowInput = _flowService.CreateFlowCard(basket);
            }

            int setCacheTime = _flowService.GetCacheMinutes(model.Pid);
            int cacheTime = (int)(model.CreatedTime - flowInput.CURRENTTIME).TotalMinutes;
            if (cacheTime > setCacheTime)
            {
                basket.Status = "4";
                basket.Remark = "外在制超时";
            }

            basket.WorkOrder = flowInput.WORKORDER;
            basket.ProductCode = flowInput.MATERIAL;
            basket.FlowNo = flowInput.FLOWNO;
            basket.WaferList = flowInput.Wafers;

            try
            {
                for (int i = 0; i < 120; i++)
                {
                    if (i >= basket.WaferList.Count)
                    {
                        basket.WaferList.Add(_waferService.CreateWafer(basket, i));
                    }
                    basket.WaferList[i].TESTID = model.WaferID[i];
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message + "\r\n" + ex.StackTrace);
            }
            //过站
            _flowService.FlowCardTrace(basket, flowInput);
            _waferService.SaveWaferId(model.Pid, basket.FlowNo, model.WaferID);
        }

        /// <summary>
        /// 下料逻辑
        /// </summary>
        /// <param name="model"></param>
        public void DownBasketTask(BM_MODEL model)
        {
            var wafers = _waferService.SwitchedWafer(model.Pid, model.WaferID);

            BasketModel basket = new BasketModel()
            {
                Eid = model.EID,
                Pid = model.Pid,
                Struid = model.Struid,
                ChannelNo = int.Parse(model.CHANEL),
                UpDown = model.UpDown,
                BoatNo = model.BoatIDNotify1,
                GrooveNo = model.BoatDataPostion1,
                TubeNo = model.UpDown == 2 ? model.StoveIDNotify1 : "",
                ProcessTime = model.CreatedTime,
                Craft = model.CraftID1,
                Status = "0"
            };
            FlowCardInput? flowCard = GetFlowCard(wafers, model.Pid, model.EID, basket.ChannelNo.ToString());

            //过站
            if (flowCard == null)
            {
                _logger.LogDebug("WaferId获取失败：" + JsonConvert.SerializeObject(model));
                flowCard = _flowService.CreateFlowCard(basket);
                wafers = flowCard.Wafers;
            }
            else if (string.IsNullOrWhiteSpace(flowCard.FLOWNO))
            {
                _logger.LogDebug($"流程卡失效：{model.Struid}-{model.EID}-{model.CreatedTime}");
                flowCard = _flowService.CreateFlowCard(basket);
                flowCard.Wafers = wafers;
                basket.Status = "2";
            }

            basket.WorkOrder = flowCard.WORKORDER;
            basket.ProductCode = flowCard.MATERIAL;
            basket.FlowNo = flowCard.FLOWNO;
            basket.Buid = flowCard.STRUID;
            basket.WaferList = wafers.Count == 0 ? flowCard.Wafers : wafers;

            int newWafers = basket.WaferList.Where(m => m.ID == 0).Count();
            if (newWafers > 0)
            {
                int idx = 0;
                var createdWafers = _waferService.CreateWafers(basket, newWafers);
                for (int i = 0; i < basket.WaferList.Count; i++)
                {
                    if (basket.WaferList[i].ID == 0)
                    {
                        basket.WaferList[i] = createdWafers[idx];
                        basket.WaferList[i].SORT = i;
                        idx++;
                    }
                    basket.WaferList[i].TESTID = model.WaferID[i];
                }
            }
            _flowService.FlowCardTrace(basket, flowCard);
        }
        /// <summary>
        /// 获取WAFER对应流程卡
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private FlowCardInput GetFlowCard(List<TBL_TRACE_WAFER> wafers, string pid, string eid, string channel)
        {
            //从WAFERID内选择一个合适的花篮UID
            List<FlowCount> flowNos = wafers.OrderBy(m => m.CURRENTTIME)
                .GroupBy(m => m.FLOWNO).Select(m => new FlowCount() { FlowNo = m.Key, Qty = m.Count() })
                .Where(m => m.Qty > 20).ToList();
            if (flowNos.Count == 1 && string.IsNullOrWhiteSpace(flowNos[0].FlowNo))
            {
                return null;
            }

            FlowCardInput? flowCard = null;
            foreach (var item in flowNos)
            {
                if (string.IsNullOrWhiteSpace(item.FlowNo))
                {
                    continue;
                }
                flowCard = _redisRepository.Get<FlowCardInput>($"FlowNo:{item.FlowNo}");

                if (flowCard == null)
                {
                    _logger.LogDebug($"未读到流程卡：{item.FlowNo}");
                    continue;
                }
                if ((flowCard.CURRENTPROCESS == pid && flowCard.UPDOWN == "0") || int.Parse(flowCard.CURRENTPROCESS) < int.Parse(pid))
                {
                    return flowCard;
                }
                flowCard = new FlowCardInput();
            }
            return flowCard;
        }

        public void CreateFlowCard(BM_MODEL model)
        {
            BasketModel basket = new BasketModel()
            {
                Eid = model.EID,
                Pid = model.Pid,
                Buid = model.Struid,
                Struid = model.Struid,
                ChannelNo = int.Parse(model.CHANEL),
                UpDown = model.UpDown,
                BoatNo = model.BoatIDNotify1,
                GrooveNo = model.BoatDataPostion1,
                TubeNo = model.UpDown == 2 ? model.StoveIDNotify1 : "",
                ProcessTime = model.CreatedTime,
                Craft = model.CraftID1,
                Status = "0"
            };
            _flowService.CreateFlowCard(basket);
        }
        #endregion
    }
}
